#include "OpenGLWindow.h"

#include "GL/GL.h"
#include "GL/GLU.h"

#include <math.h>

OpenGLWindow::OpenGLWindow(std::wstring title,unsigned int width, unsigned int height):
	Window(title,width,height),
	m_Running(true),
	m_Bits(32)
{
	
}


OpenGLWindow::~OpenGLWindow(void)
{

}

void OpenGLWindow::Repaint()
{
	m_pPaintThread->enter();
	Draw();
	::SwapBuffers(m_hDC);
	glFinish();
	m_pPaintThread->leave();
}

void OpenGLWindow::Run()
{
	wglMakeCurrent(m_hDC,m_hRC);
	Init();
	Resize(m_Width,m_Height);

	while( m_Running ){
		wglMakeCurrent(m_hDC,m_hRC);
		Repaint();
	}

	if (m_hRC)											
	{
		// make sure the rendering context is no longer current.
		wglMakeCurrent(NULL,NULL);
		// delete the rendering context
		wglDeleteContext(m_hRC);						
		m_hRC=NULL;										
	}
}

bool OpenGLWindow::Init()
{
	glShadeModel(GL_SMOOTH);							
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				
	glClearDepth(1.0f);									
	glEnable(GL_DEPTH_TEST);							
	glDepthFunc(GL_LEQUAL);								
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	
	return true;	
}

void OpenGLWindow::Resize(unsigned int width, unsigned int height)
{
	m_Width= width;
	m_Height = height > 0 ? height:1;

	glViewport(0,0,m_Width,m_Height);						

	glMatrixMode(GL_PROJECTION);					
	glLoadIdentity();								

	// Calculate The Aspect Ratio Of The Window
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
	gluLookAt(1,1,1,0,0,0,0,0,1);

	glMatrixMode(GL_MODELVIEW);							
	glLoadIdentity();									
}

 
bool OpenGLWindow::Create()
{
	WNDCLASSEX	wc;
	// background must be set to NULL, to avoid flickering
	this->CreateDefaultWindowClass(wc,NULL);

	DWORD dwExStyle, dwStyle ;

	dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;			
	dwStyle=WS_OVERLAPPEDWINDOW;							

	CreateStyledWindow(dwExStyle,dwStyle);
	
	GLuint		PixelFormat;
	static	PIXELFORMATDESCRIPTOR pfd=				
	{
		sizeof(PIXELFORMATDESCRIPTOR),				
		1,											
		PFD_DRAW_TO_WINDOW |						
		PFD_SUPPORT_OPENGL |						
		PFD_DOUBLEBUFFER,							
		PFD_TYPE_RGBA,								
		m_Bits,										
		0, 0, 0, 0, 0, 0,							
		0,											
		0,											
		0,											
		0, 0, 0, 0,									
		16,											
		0,											
		0,											
		PFD_MAIN_PLANE,								
		0,											
		0, 0, 0										
	};
	
	if (!(m_hDC=GetDC(m_hWnd)))							
	{
		Kill();								
		MessageBox(NULL,L"Can't Create A GL Device Context.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
		return false;						
	}

	if (!(PixelFormat=ChoosePixelFormat(m_hDC,&pfd)))	
	{
		Kill();								
		MessageBox(NULL,L"Can't Find A Suitable PixelFormat.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
		return false;								
	}

	if(!SetPixelFormat(m_hDC,PixelFormat,&pfd))		
	{
		Kill();								
		MessageBox(NULL,L"Can't Set The PixelFormat.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
		return false;							
	}

	if (!(m_hRC=wglCreateContext(m_hDC)))				
	{
		Kill();								
		MessageBox(NULL,L"Can't Create A GL Rendering Context.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
		return false;						
	}

	ShowWindow(m_hWnd,SW_SHOW);						
	SetForegroundWindow(m_hWnd);					
	SetFocus(m_hWnd);								

	m_pPaintThread =new Thread(this);
	m_pPaintThread->start();
	return true;									
}

bool OpenGLWindow::Kill()								
{
	m_Running = false;
	bool killSuccess = true;
	if (m_hDC && !ReleaseDC(m_hWnd,m_hDC))
	{
		killSuccess = false;
	}

	if (m_hWnd && !DestroyWindow(m_hWnd))				
	{
		killSuccess = false;						
	}

	if (!UnregisterClass(L"Window",m_hInstance))			
	{
		killSuccess = false;
	}

	m_hDC=NULL;
    m_hWnd=NULL;
    m_hInstance=NULL;
    return killSuccess;
	return killSuccess;
}

	
void OpenGLWindow::DrawGrid(int nrOfLines, float gridSize)
{
	float min = -gridSize * nrOfLines/2;
	float max = gridSize* nrOfLines/2;
	glBegin(GL_LINES);
	glColor3ub(255,0,0);
	for ( int x = 0; x < nrOfLines/2; ++x)
	{
		glVertex3f(x*gridSize,min,0);
		glVertex3f(x*gridSize,max,0);
	}
	glColor3ub(255,115,115);
	for ( int x = 1; x < nrOfLines/2; ++x)
	{
		glVertex3f(-x*gridSize,min,0);
		glVertex3f(-x*gridSize,max,0);
	}
	glColor3ub(0,255,0);
	for ( int y = 0; y < nrOfLines/2; ++y)
	{
		glVertex3f(min,y*gridSize,0);
		glVertex3f(max,y*gridSize,0);
	}
	glColor3ub(200,255,200);
	for ( int y = 1; y < nrOfLines/2; ++y)
	{
		glVertex3f(min,-y*gridSize,0);
		glVertex3f(max,-y*gridSize,0);
	}
	glEnd();
}

void OpenGLWindow::Draw()
{
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer
	glLoadIdentity();									// Reset The Current Modelview Matrix
	DrawGrid(20,0.2f);	
}